package club.banyuan;

import club.banyuan.util.HrmSession;
import club.banyuan.util.SessionUtil;
import com.alibaba.fastjson.JSONObject;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class HttpServer {
    private static final UserService userService = UserService.getINSTANCE();
    private static final DeptService deptService = DeptService.getINSTANCE();
    private static final PositionService positionService = PositionService.getINSTANCE();
    private static final EmployeeService employeeService = EmployeeService.getINSTANCE();

    public static EmployeeService getEmployeeService() {
        return employeeService;
    }

    public static UserService getUserService() {
        return userService;
    }

    public static DeptService getDeptService() {
        return deptService;
    }

    public static PositionService getPositionService() {
        return positionService;
    }

    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(5000);

        while (true) {
            System.out.println("等待浏览器");
            Socket socket = serverSocket.accept();
            InputStream inputStream = socket.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));

            Request request = Request.parse(reader);
            if (request == null) {
                System.out.println("解析失败");
                continue;
            }

            System.out.println("向浏览器写入数据");
            OutputStream outputStream = socket.getOutputStream();
            String url = request.getUrl();
            String resourcePath = "/static";
            if ("/".equals(url)) {
                resourcePath += "/login.html";
                writeStaticResource(outputStream, resourcePath, request);
            } else if (url.startsWith("/css") || url.startsWith("/images")
                    || url.startsWith("/js") || url.endsWith(".html") || url.startsWith("/jquery-easyui-1.3.3")) {
                resourcePath += url;
                //页面不存在
                if (resourcePath.endsWith(".html")
                        && HttpServer.class.getResource(resourcePath) == null) {
                    resourcePath = "/pages/404.html";
                }
                //用户未登录
                if (!resourcePath.endsWith("login.html") && resourcePath.endsWith(".html")
                        && request.getSession().get("user") == null) {
                    setRedirect(outputStream, request, "/login.html");
                }
                writeStaticResource(outputStream, resourcePath, request);
            } else if (url.startsWith("/admin") || url.startsWith("/dept")
                    || url.startsWith("/position") || url.startsWith("/empl")) {
                try {
                    processData(outputStream, request);
                } catch (BadRequestException e) {
                    sendBadRequest(outputStream, e);
                } catch (Exception e) {
                    System.out.println(e.getMessage());
                }
            } else {
                System.out.println("路径不合法");
                continue;
            }
            socket.close();
        }
    }

    private static void processData(OutputStream outputStream, Request request) throws IOException {
        String url = request.getUrl();
        //用户未登录,没有重定向
        validateAuth(url, request);
        List<Position> positionList = positionService.getPositionList();
        List<Dept> deptList = deptService.getDeptList();
        List<User> userList = userService.getUserList();

        switch (url) {
            case "/admin/login": {
                if (request.getData() == null) {
                    setRedirect(outputStream, request, "/login.html");
                } else {
                    Map<String, String> formData = request.getFormData();
                    System.out.println(formData);
                    User user = new User();
                    user.setUsername(formData.get("username"));
                    user.setPassword(formData.get("password"));
                    user.setRolename("admin");
                    User loginUser = userService.userLogin(user);
                    System.out.println(loginUser);
                    if (loginUser == null) {
                        setRedirect(outputStream, request, "/login.html");
                    } else {
                        request.getSession().put("user", loginUser);
                        setRedirect(outputStream, request, "/home_page.html");
                    }
                }
            }
            break;
            case "/admin/list": {
                System.out.println("查询用户列表");
                List<User> rowsList;
                //try {
                Map<String, String> formData = request.getFormData();
                System.out.println(formData);
                int page = Integer.parseInt(formData.get("page"));
                int rows = Integer.parseInt(formData.get("rows"));
                String username = formData.get("username");
                rowsList = userService.getRowsList(page, rows, username);
                //} catch (Exception e) {
                //   operationHint(outputStream, request, 1, "服务器异常");
                //}
                //操作成功
                Map<String, Object> rlt = new HashMap<>();
                rlt.put("total", userList.size());
                rlt.put("code", 0);
                rlt.put("message", "");
                rlt.put("rows", rowsList);
                sendJsonResponse(outputStream, rlt, request);
            }
            break;
            case "/admin/save": {
                System.out.println("新增或修改管理员信息");
                Map<String, String> formData = request.getFormData();
                System.out.println(formData);
                String s = JSONObject.toJSONString(formData);
                User user = JSONObject.parseObject(s, User.class);
                user.setRolename("admin");

                if (user.getId() == 0) {
                    try {
                        userService.addUser(user);
                    } catch (Exception e) {
                        //操作失败
                        operationHint(outputStream, request, 1, "管理员名称重复");
                    }
                } else {
                    userService.updateUser(user);
                }
                //操作成功
                operationHint(outputStream, request, 0, "");
            }
            break;
            case "/admin/delete": {
                System.out.println("删除管理员");
                try {
                    Map<String, String> formData = request.getFormData();
                    String[] ids = formData.get("ids").split(",");
                    for (String id : ids) {
                        userService.deleteUser(Integer.parseInt(id));
                    }
                } catch (Exception e) {
                    operationHint(outputStream, request, 1, "删除失败");
                }
                //操作成功
                operationHint(outputStream, request, 0, "");
            }
            break;
            case "/admin/info": {
                Object loginUser = request.getSession().get("user");
                //System.out.println(loginUser);
                Map<String, Object> rlt = new HashMap<>();
                rlt.put("code", 0);
                rlt.put("message", "");
                rlt.put("username", loginUser.toString());
                sendJsonResponse(outputStream, rlt, request);
            }
            break;
            case "/admin/logout": {
                HrmSession session = request.getSession();
                SessionUtil.invalidateSession(session);
                session.invalidate();
                setRedirect(outputStream, request, "/login.html");
            }
            break;
            case "/dept/list": {
                System.out.println("查询部门列表");
                //formData有默认值:name=&page=1&rows=10
                List<Dept> rowsList;
                //try {
                Map<String, String> formData = request.getFormData();
                int page = Integer.parseInt(formData.get("page"));
                int rows = Integer.parseInt(formData.get("rows"));
                String name = formData.get("name");
                rowsList = deptService.getRowsList(page, rows, name);
                //} catch (Exception e) {
                //   operationHint(outputStream, request, 1, "服务器异常");
                //}
                //操作成功
                Map<String, Object> rlt = new HashMap<>();
                rlt.put("total", deptList.size());
                rlt.put("code", 0);
                rlt.put("message", "");
                rlt.put("rows", rowsList);
                sendJsonResponse(outputStream, rlt, request);
            }
            break;
            case "/dept/save": {
                System.out.println("新增或修改部门信息");
                Map<String, String> formData = request.getFormData();
                System.out.println(formData);
                String s = JSONObject.toJSONString(formData);
                Dept dept = JSONObject.parseObject(s, Dept.class);

                if (dept.getId() == 0) {
                    try {
                        deptService.addDept(dept);
                    } catch (Exception e) {
                        //操作失败
                        operationHint(outputStream, request, 1, "部门名称重复");
                    }
                } else {
                    deptService.updateDept(dept);
                }
                //操作成功
                operationHint(outputStream, request, 0, "");
            }
            break;
            case "/dept/delete": {
                System.out.println("删除部门");
                try {
                    Map<String, String> formData = request.getFormData();
                    String[] ids = formData.get("ids").split(",");
                    for (String id : ids) {
                        deptService.deleteDept(Integer.parseInt(id));
                    }
                } catch (Exception e) {
                    operationHint(outputStream, request, 1, "删除失败");
                }
                //操作成功
                operationHint(outputStream, request, 0, "");
            }
            break;
            case "/dept/getcombobox": {
                System.out.println("员工下拉列表查询部门");
                //操作成功
                sendJsonResponse(outputStream, deptList, request);
            }
            break;
            case "/position/list": {
                System.out.println("查询职位列表");
                //formData有默认值:name=&page=1&rows=10
                List<Position> rowsList;
                //try {
                Map<String, String> formData = request.getFormData();
                int page = Integer.parseInt(formData.get("page"));
                int rows = Integer.parseInt(formData.get("rows"));
                String name = formData.get("name");
                rowsList = positionService.getRowsList(page, rows, name);
                //} catch (Exception e) {
                //   operationHint(outputStream, request, 1, "服务器异常");
                //}
                //操作成功
                Map<String, Object> rlt = new HashMap<>();
                rlt.put("total", positionList.size());
                rlt.put("code", 0);
                rlt.put("message", "");
                rlt.put("rows", rowsList);
                sendJsonResponse(outputStream, rlt, request);
            }
            break;
            case "/position/save": {
                System.out.println("新增或修改职位信息");
                Map<String, String> formData = request.getFormData();
                System.out.println(formData);
                String s = JSONObject.toJSONString(formData);
                Position position = JSONObject.parseObject(s, Position.class);

                if (position.getId() == 0) {
                    try {
                        positionService.addPosition(position);
                    } catch (Exception e) {
                        //操作失败
                        operationHint(outputStream, request, 1, "职位名称重复");
                    }
                } else {
                    positionService.updatePosition(position);
                }
                //操作成功
                operationHint(outputStream, request, 0, "");
            }
            break;
            case "/position/delete": {
                System.out.println("删除部门");
                try {
                    Map<String, String> formData = request.getFormData();
                    String[] ids = formData.get("ids").split(",");
                    for (String id : ids) {
                        positionService.deletePosition(Integer.parseInt(id));
                    }
                } catch (Exception e) {
                    operationHint(outputStream, request, 1, "删除失败");
                }
                //操作成功
                operationHint(outputStream, request, 0, "");
            }
            break;
            case "/position/getcombobox": {
                System.out.println("员工下拉列表查询职位");
                //操作成功
                sendJsonResponse(outputStream, positionList, request);
            }
            break;
            case "/empl/list": {
                System.out.println("查询员工列表");
                //formData有默认值:name=&page=1&rows=10
                List<Employee> rowsList;
                //try {
                Map<String, String> formData = request.getFormData();
                System.out.println(formData);
                int page = Integer.parseInt(formData.get("page"));
                int rows = Integer.parseInt(formData.get("rows"));
                String id = formData.get("id");
                String name = formData.get("name");
                String departmentName = formData.get("departmentName");
                String positionName = formData.get("positionName");
                String sex = formData.get("sex");
                rowsList = employeeService.getRowsList(page, rows,
                        id, name, departmentName, positionName, sex);
                //} catch (Exception e) {
                //   operationHint(outputStream, request, 1, "服务器异常");
                //}
                //操作成功
                Map<String, Object> rlt = new HashMap<>();
                rlt.put("total", employeeService.getEmployeeList().size());
                rlt.put("code", 0);
                rlt.put("message", "");
                rlt.put("rows", rowsList);
                sendJsonResponse(outputStream, rlt, request);
            }
            break;
            case "/empl/save": {
                System.out.println("新增或修改员工信息");
                Map<String, String> formData = request.getFormData();
                String updateFlag = formData.get("updateFlag");
                formData.remove("updateFlag");
                int departmentId = Integer.parseInt(formData.get("departmentId"));
                int positionId = Integer.parseInt(formData.get("positionId"));
                String s = JSONObject.toJSONString(formData);
                Employee employee = JSONObject.parseObject(s, Employee.class);
                employee.setDepartmentName(employee.getDepartmentName());
                employee.setPositionName(employee.getPositionName());

                if (updateFlag.equals("no")) {
                    try {
                        employeeService.addEmployee(employee);
                    } catch (Exception e) {
                        //操作失败
                        operationHint(outputStream, request, 1, "员工id重复");
                    }
                } else if (updateFlag.equals("yes")) {
                    employeeService.updateEmployee(employee);
                }
                //操作成功
                operationHint(outputStream, request, 0, "");
            }
            break;
            case "/empl/delete": {
                System.out.println("删除员工");
                try {
                    Map<String, String> formData = request.getFormData();
                    String[] ids = formData.get("ids").split(",");
                    for (String id : ids) {
                        employeeService.deleteEmployee(Integer.parseInt(id));
                    }
                } catch (Exception e) {
                    operationHint(outputStream, request, 1, "删除失败");
                }
                //操作成功
                operationHint(outputStream, request, 0, "");
            }
            break;
        }
    }

    private static void operationHint(OutputStream outputStream, Request request, int code, String hint) throws IOException {
        Map<String, Object> rlt = new HashMap<>();
        rlt.put("code", code);
        rlt.put("message", hint);
        sendJsonResponse(outputStream, rlt, request);
    }

    private static void sendJsonResponse(OutputStream outputStream, Object object, Request request)
            throws IOException {
        String msg = JSONObject.toJSONString(object);

        outputStream.write("HTTP/1.1 200 OK\n".getBytes());
        outputStream.write("Content-Type: application/json; charset=utf-8\n".getBytes());
        outputStream.write(("Content-Length: " + msg.getBytes().length).getBytes());
        outputStream.write("\n".getBytes());
        writeCookie(outputStream, request);
        outputStream.write("\n".getBytes());
        outputStream.write(msg.getBytes());
    }

    private static void sendOk(OutputStream outputStream, Request request)
            throws IOException {
        outputStream.write("HTTP/1.1 200 OK\n".getBytes());
        writeCookie(outputStream, request);
        outputStream.write("\n".getBytes());
    }

    private static void writeCookie(OutputStream outputStream, Request request) throws IOException {
        HrmSession session = request.getSession();
        if (session.isValid()) {
            //生效
            outputStream.write(("Set-Cookie: SESSIONID=" + session.getSessionId()).getBytes());
        } else {
            //失效
            //Max-Age 通知浏览器, cookie的有效时间, 秒为单位
            outputStream.write(("Set-Cookie: SESSIONID=" + session.getSessionId() + ";Max-Age=0").getBytes());
        }
        outputStream.write(("\n").getBytes());
    }

    private static void setRedirect(OutputStream outputStream, Request request, String s) throws IOException {
        outputStream.write("HTTP/1.1 302 Found\n".getBytes());
        outputStream.write(("Location: " + "http://" + request.getHost() + s).getBytes());
        outputStream.write("\n".getBytes());
    }

    private static void writeStaticResource(OutputStream outputStream, String resourcePath, Request request) throws IOException {

        BufferedInputStream bufferedInputStream = new BufferedInputStream(HttpServer.class.getResourceAsStream(resourcePath));
        int available = bufferedInputStream.available();

        outputStream.write("HTTP/1.1 200 OK\n".getBytes());
        //html文件需要加
        if (resourcePath.endsWith(".html")) {
            outputStream.write("Content-Type: text/html; charset=utf-8\n".getBytes());
        }

        outputStream.write(("Content-Length: " + available + "\n").getBytes());
        writeCookie(outputStream, request);
        outputStream.write("\n".getBytes());

        byte[] buf = new byte[1024];
        int count = bufferedInputStream.read(buf);
        while (count > 0) {
            outputStream.write(buf, 0, count);
            count = bufferedInputStream.read(buf);
        }

        bufferedInputStream.close();
    }

    private static void sendBadRequest(OutputStream outputStream, BadRequestException e)
            throws IOException {
        outputStream.write("HTTP/1.1 400 Bad request\n".getBytes());
        byte[] msgBytes = e.getMessage().getBytes();
        outputStream.write("Content-Type: text/plain; charset=UTF-8\n".getBytes());
        outputStream.write(("Content-Length: " + msgBytes.length).getBytes());
        outputStream.write("\n\n".getBytes());
        outputStream.write(msgBytes);
    }

    private static void validateAuth(String url, Request request) {
        // 过滤白名单，出现在这里的url，不需要进行权限判断
        List<String> whiteList = new ArrayList<>();
        whiteList.add("/admin/login");
        if (whiteList.contains(url)) {
            return;
        }
        Object user = request.getSession().get("user");
        if (user == null) {
            // 用户未登录
            throw new BadRequestException("用户未登录");
        }
    }
}
